package uk.co.mmscomputing.device.capi.sound;

import java.io.*;
import uk.co.mmscomputing.device.capi.*;

public class PCMInputStream extends FilterInputStream{

  /*
    Convert ISDN 'raw' byte stream into mono PCM byte stream

    PCM 8000.0 Hz, 16 bit, mono, SIGNED, little-endian
    static AudioFormat pcmformat = new AudioFormat(8000,16,1,true,false);

  */

  static private int[]   alawtable={
    0x80ea,0x8015,0xa8fe,0x5801,0x00aa,0x0056,0xa0fa,0x6005,
    0x40f5,0xc00a,0xa8ff,0x5800,0x00d5,0x002b,0x50fd,0xb002,
    0x80e2,0x801d,0x28fe,0xd801,0x008a,0x0076,0xa0f8,0x6007,
    0x40f1,0xc00e,0x28ff,0xd800,0x00c5,0x003b,0x50fc,0xb003,
    0x80ee,0x8011,0xe8fe,0x1801,0x00ba,0x0046,0xa0fb,0x6004,
    0x40f7,0xc008,0xe8ff,0x1800,0x00dd,0x0023,0xd0fd,0x3002,
    0x80e6,0x8019,0x68fe,0x9801,0x009a,0x0066,0xa0f9,0x6006,
    0x40f3,0xc00c,0x68ff,0x9800,0x00cd,0x0033,0xd0fc,0x3003,
    0x80e8,0x8017,0x88fe,0x7801,0x00a2,0x005e,0x20fa,0xe005,
    0x40f4,0xc00b,0x88ff,0x7800,0x00d1,0x002f,0x10fd,0xf002,
    0x80e0,0x801f,0x08fe,0xf801,0x0082,0x007e,0x20f8,0xe007,
    0x40f0,0xc00f,0x08ff,0xf800,0x00c1,0x003f,0x10fc,0xf003,
    0x80ec,0x8013,0xc8fe,0x3801,0x00b2,0x004e,0x20fb,0xe004,
    0x40f6,0xc009,0xc8ff,0x3800,0x00d9,0x0027,0x90fd,0x7002,
    0x80e4,0x801b,0x48fe,0xb801,0x0092,0x006e,0x20f9,0xe006,
    0x40f2,0xc00d,0x48ff,0xb800,0x00c9,0x0037,0x90fc,0x7003,
    0x80eb,0x8014,0xb8fe,0x4801,0x00ae,0x0052,0xe0fa,0x2005,
    0xc0f5,0x400a,0xb8ff,0x4800,0x00d7,0x0029,0x70fd,0x9002,
    0x80e3,0x801c,0x38fe,0xc801,0x008e,0x0072,0xe0f8,0x2007,
    0xc0f1,0x400e,0x38ff,0xc800,0x00c7,0x0039,0x70fc,0x9003,
    0x80ef,0x8010,0xf8fe,0x0801,0x00be,0x0042,0xe0fb,0x2004,
    0xc0f7,0x4008,0xf8ff,0x0800,0x00df,0x0021,0xf0fd,0x1002,
    0x80e7,0x8018,0x78fe,0x8801,0x009e,0x0062,0xe0f9,0x2006,
    0xc0f3,0x400c,0x78ff,0x8800,0x00cf,0x0031,0xf0fc,0x1003,
    0x80e9,0x8016,0x98fe,0x6801,0x00a6,0x005a,0x60fa,0xa005,
    0xc0f4,0x400b,0x98ff,0x6800,0x00d3,0x002d,0x30fd,0xd002,
    0x80e1,0x801e,0x18fe,0xe801,0x0086,0x007a,0x60f8,0xa007,
    0xc0f0,0x400f,0x18ff,0xe800,0x00c3,0x003d,0x30fc,0xd003,
    0x80ed,0x8012,0xd8fe,0x2801,0x00b6,0x004a,0x60fb,0xa004,
    0xc0f6,0x4009,0xd8ff,0x2800,0x00db,0x0025,0xb0fd,0x5002,
    0x80e5,0x801a,0x58fe,0xa801,0x0096,0x006a,0x60f9,0xa006,
    0xc0f2,0x400d,0x58ff,0xa800,0x00cb,0x0035,0xb0fc,0x5003
  };

  static private int[]   ulawtable={                         
    0x8482,0x7c7d,0xa4f8,0x5c07,0x04e1,0xfc1e,0x8cfe,0x7401,
    0x84c1,0x7c3e,0x94fc,0x6c03,0xc4f0,0x3c0f,0x88ff,0x7800,
    0x84a2,0x7c5d,0xa4fa,0x5c05,0x04e9,0xfc16,0x0cff,0xf400,
    0x84d1,0x7c2e,0x94fd,0x6c02,0xc4f4,0x3c0b,0xc8ff,0x3800,
    0x8492,0x7c6d,0xa4f9,0x5c06,0x04e5,0xfc1a,0xccfe,0x3401,
    0x84c9,0x7c36,0x14fd,0xec02,0xc4f2,0x3c0d,0xa8ff,0x5800,
    0x84b2,0x7c4d,0xa4fb,0x5c04,0x04ed,0xfc12,0x4cff,0xb400,
    0x84d9,0x7c26,0x14fe,0xec01,0xc4f6,0x3c09,0xe8ff,0x1800,
    0x848a,0x7c75,0x24f9,0xdc06,0x04e3,0xfc1c,0xacfe,0x5401,
    0x84c5,0x7c3a,0xd4fc,0x2c03,0xc4f1,0x3c0e,0x98ff,0x6800,
    0x84aa,0x7c55,0x24fb,0xdc04,0x04eb,0xfc14,0x2cff,0xd400,
    0x84d5,0x7c2a,0xd4fd,0x2c02,0xc4f5,0x3c0a,0xd8ff,0x2800,
    0x849a,0x7c65,0x24fa,0xdc05,0x04e7,0xfc18,0xecfe,0x1401,
    0x84cd,0x7c32,0x54fd,0xac02,0xc4f3,0x3c0c,0xb8ff,0x4800,
    0x84ba,0x7c45,0x24fc,0xdc03,0x04ef,0xfc10,0x6cff,0x9400,
    0x84dd,0x7c22,0x54fe,0xac01,0xc4f7,0x3c08,0xf8ff,0x0800,
    0x8486,0x7c79,0xe4f8,0x1c07,0x04e2,0xfc1d,0x9cfe,0x6401,
    0x84c3,0x7c3c,0xb4fc,0x4c03,0x44f1,0xbc0e,0x90ff,0x7000,
    0x84a6,0x7c59,0xe4fa,0x1c05,0x04ea,0xfc15,0x1cff,0xe400,
    0x84d3,0x7c2c,0xb4fd,0x4c02,0x44f5,0xbc0a,0xd0ff,0x3000,
    0x8496,0x7c69,0xe4f9,0x1c06,0x04e6,0xfc19,0xdcfe,0x2401,
    0x84cb,0x7c34,0x34fd,0xcc02,0x44f3,0xbc0c,0xb0ff,0x5000,
    0x84b6,0x7c49,0xe4fb,0x1c04,0x04ee,0xfc11,0x5cff,0xa400,
    0x84db,0x7c24,0x34fe,0xcc01,0x44f7,0xbc08,0xf0ff,0x1000,
    0x848e,0x7c71,0x64f9,0x9c06,0x04e4,0xfc1b,0xbcfe,0x4401,
    0x84c7,0x7c38,0xf4fc,0x0c03,0x44f2,0xbc0d,0xa0ff,0x6000,
    0x84ae,0x7c51,0x64fb,0x9c04,0x04ec,0xfc13,0x3cff,0xc400,
    0x84d7,0x7c28,0xf4fd,0x0c02,0x44f6,0xbc09,0xe0ff,0x2000,
    0x849e,0x7c61,0x64fa,0x9c05,0x04e8,0xfc17,0xfcfe,0x0401,
    0x84cf,0x7c30,0x74fd,0x8c02,0x44f4,0xbc0b,0xc0ff,0x4000,
    0x84be,0x7c41,0x64fc,0x9c03,0x04f0,0xfc0f,0x7cff,0x8400,
    0x84df,0x7c20,0x74fe,0x8c01,0x44f8,0xbc07,0x0000,0x0000
  };

  private int[]   table=null;

  public PCMInputStream(InputStream in, boolean useALaw)throws IOException{
    super(in);
    table=(useALaw)?alawtable:ulawtable;
  }

  public int read()throws IOException{
    throw new IOException(getClass().getName()+".read() :\n\tDo not support simple read().");
  }

  public int read(byte[] b, int off, int len)throws IOException{
    byte[]  inb;
    int     value;

    inb=new byte[len>>1];                      // get A-Law or u-Law bytes
    len=in.read(inb);
    if(len==-1){return -1;};

    for(int i=0;i<len;i++){
      value  = table[inb[i]&0x00FF];
      b[off++]=(byte)((value>>8)&0x00FF);      // little-endian
      b[off++]=(byte)(value&0x00FF);
    }
    return len<<1;
  }
/*
  public int read(byte[] b, int off, int len)throws IOException{
    int sample, value;

    int i   = off;
    int max = off+len-1;                       // why -1 : because we need space for two bytes
    while(i<max){
      sample = in.read();
      if(sample==-1){
        if(i==off){return -1;}                 // end of stream
        break;
      }
      value  = table[sample];
      b[i++]=(byte)((value>>8)&0x00FF);        // little-endian
      b[i++]=(byte)(value&0x00FF);
    }
    return i-off;
  }
*/

  public synchronized int available()throws IOException{
    return super.available()<<1;               // two PCM bytes for one A-Law u-Law byte
  }
}




